﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using MishraReader.ViewModels;
using System.Collections;
using System.Windows.Data;

namespace MishraReader.Windows.Controls
{
    public class FeedItemsListBox : ListBox
    {
        private const int FirstItemAnimationDelay = 30;
        private const int ItemsAnimationDelay = 50;
        private const double ScrollToBottomThreshold = 10;


        public static readonly DependencyProperty RequireMoreDataCommandProperty =
            DependencyProperty.Register("RequireMoreDataCommand", typeof(ICommand), typeof(FeedItemsListBox),
                                        new UIPropertyMetadata(null));

        private bool _disableAnimation;
        private bool _isFirstResize;
        private bool _isLoaded;


        private ScrollViewer _scrollViewer;

        static FeedItemsListBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(FeedItemsListBox),
                                                     new FrameworkPropertyMetadata(typeof(FeedItemsListBox)));
            ItemsSourceProperty.OverrideMetadata(typeof(FeedItemsListBox),
                                                 new FrameworkPropertyMetadata(OnItemsSourcePropertyChanged));
        }

        public FeedItemsListBox()
        {
            ReactiveAnimation();
            Loaded += FeedItemsListBox_Loaded;
            Unloaded += FeedItemsListBox_Unloaded;
            SizeChanged += FeedItemsListBox_SizeChanged;
        }

        public ICommand RequireMoreDataCommand
        {
            get { return (ICommand)GetValue(RequireMoreDataCommandProperty); }
            set { SetValue(RequireMoreDataCommandProperty, value); }
        }

        public override void OnApplyTemplate()
        {
            if (_scrollViewer != null)
                _scrollViewer.ScrollChanged -= _scrollViewer_ScrollChanged;

            _scrollViewer = (ScrollViewer)GetTemplateChild("PART_ScrollViewer");
            _scrollViewer.ScrollChanged += _scrollViewer_ScrollChanged;

            base.OnApplyTemplate();
        }

        public void ReactiveAnimation()
        {
            _isFirstResize = true;
            _disableAnimation = false;
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            //Debug.WriteLine("GetContainerForItemOverride");

            return new FeedItemsListBoxItem(this);
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is FeedItemsListBoxItem;
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            /*  var offset = _scrollViewer.VerticalOffset;
            int index = ItemContainerGenerator.IndexFromContainer(element);

            Debug.WriteLine(offset +  " " + index);
*/
            var frameworkElement = (FeedItemsListBoxItem)element;

            // var sb = frameworkElement.Storyboard;

            frameworkElement.SetValue(OpacityProperty, _disableAnimation ? 1D : 0D);

            base.PrepareContainerForItemOverride(element, item);
        }

        internal double GetDelay(FeedItemsListBoxItem feedItemsListBoxItem)
        {
            var index = ItemContainerGenerator.IndexFromContainer(feedItemsListBoxItem);
            return index*ItemsAnimationDelay + FirstItemAnimationDelay;
        }

        private void CheckMoreData()
        {
            if (_isLoaded == false)
                return;

            if (_scrollViewer.ContentVerticalOffset + ScrollToBottomThreshold >= _scrollViewer.ScrollableHeight)
            {
                if (RequireMoreDataCommand != null)
                {
                    if (RequireMoreDataCommand.CanExecute(null))
                        RequireMoreDataCommand.Execute(null);
                }
            }
        }

        private void ItemsSourceChanged(bool wasEmpty)
        {
            var items = ItemsSource as IFeedItemsCollection;
            if (items == null)
            {
                // check for a collection view
                var cv = ItemsSource as ICollectionView;

                if (cv != null)
                {
                    items = cv.SourceCollection as IFeedItemsCollection;
                }
            }

            if (items != null)
            {
                if (items.IsNewData || wasEmpty == false)
                    ReactiveAnimation();
                else
                    _disableAnimation = true;
            }
            else
                ReactiveAnimation();

            if (_scrollViewer != null && _disableAnimation == false)
                _scrollViewer.ScrollToHome();
        }

        private void FeedItemsListBox_Loaded(object sender, RoutedEventArgs e)
        {
            _isFirstResize = true;
            _isLoaded = true;
            ReactiveAnimation();
        }

        private void FeedItemsListBox_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (_isLoaded)
            {
                if (_isFirstResize == false)
                    _disableAnimation = true;

                _isFirstResize = false;
            }
        }

        private void FeedItemsListBox_Unloaded(object sender, RoutedEventArgs e)
        {
            _isLoaded = false;
        }

        private void _scrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (_isLoaded == false)
                return;

            // Skip reset scroll bar
            if (_disableAnimation == false && _scrollViewer.ContentVerticalOffset == 0)
                return;

            if (_disableAnimation == false)
                _disableAnimation = true;

            CheckMoreData();
        }

        private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var lst = (FeedItemsListBox)d;

            ListCollectionView list = e.OldValue == null ? null : e.OldValue as ListCollectionView;
            bool isEmpty = true;
            if (list != null)
                isEmpty = list.Count != 0;

            lst.ItemsSourceChanged(isEmpty);
        }

        public class FeedItemsListBoxItem : ListBoxItem
        {
            private readonly FeedItemsListBox _parent;

            public FeedItemsListBoxItem(FeedItemsListBox parent)
            {
                _parent = parent;
                var sb = (Storyboard)FindResource("MetroFromBottomFadeSlideFast");
                Storyboard = sb.Clone();
                var group = new TransformGroup();
                group.Children.Add(new TranslateTransform());
                RenderTransform = group;

                Loaded += OnLoaded;
            }


            public Storyboard Storyboard { get; set; }

            private void OnLoaded(object sender, RoutedEventArgs e)
            {
                if (_parent._disableAnimation)
                {
                    Storyboard.Stop();
                    SetValue(OpacityProperty, 1D);
                }
                else
                {
                    SetCurrentValue(OpacityProperty, 0D);
                    Storyboard.BeginTime = TimeSpan.FromMilliseconds(_parent.GetDelay(this));
                    BeginStoryboard(Storyboard);
                }
            }
        }
    }
}